package restful.struts2;

import java.net.*;
import java.util.*;

import net.sf.json.*;

public class QueryString2Json extends HashMap {
	public static final QueryString2Json queryString2Json(String queryString) {
		return new QueryString2Json(queryString);
	}

	private Scanner scanner;

	private String queryString;

	public QueryString2Json(String queryString) {
		this.queryString = queryString;
		startScanning();
	}

	private Map array(String name)
	{
		if(!containsKey(name)) put(name, new HashMap());
		return (Map) get(name);
	}

	private void continueScanning() {
		while (scanner.hasNext())
			scan(scanner.next());
	}
	
	private String decode(String string) {
		try {
			return URLDecoder.decode(string, "UTF-8");
		} catch (Exception e) {
			return string;
		}
	}
	
	private String indexFrom(String string)
	{
		return string.replaceAll(".*\\[", "").replaceAll("\\].*", "");
	}
	
	private boolean isArray(String string)
	{
		boolean containsBracket = string.contains("[") || string.contains("]");
		
		return containsBracket;
	}
	
	private boolean isValue(String string) {
		boolean notContainsBracket = !(string.contains("[") && string.contains("]"));

		return notContainsBracket;
	}
	
	private String nameFrom(String string)
	{
		return string.replaceAll("\\[.*", "");
	}
	
	private void putArray(String nameAndIndex, String value) {
		String name = nameFrom(nameAndIndex);
		String index = indexFrom(nameAndIndex);
		
		array(name).put(index, value);
	}

	private void putArrayOrValue(String name, String value)
	{
		if(isArray(name)) putArray(name, value);
		if(isValue(name)) put(name, value);
	}

	private void scan(String string) {
		Scanner parameterScanner = new Scanner(string).useDelimiter("=");
		String name = parameterScanner.next();
		String value = parameterScanner.next();
		putArrayOrValue(decode(name), decode(value));
	}

	private void startScanning() {
		scanner = new Scanner(queryString).useDelimiter("&");
		continueScanning();
	}

	public String toJson() {
		return JSONObject.fromObject(this).toString();
	}
}
